# coding = utf-8

'''
该文件里面包含的代码包括的功能包括：
（1）读取数据，得到肿瘤和肝脏金标准，肿瘤和肝脏预测值，肿瘤预测概率值
(2)计算dice进行验证
'''

import os
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

import numpy as np
from scipy import ndimage
from skimage import measure

def select_tumor(output, label, prob):
    predict_liver = np.zeros(output.shape)
    predict_tumor = np.zeros(output.shape)
    predict_liver[output>=1] = 1
    predict_tumor[output == 2] = 1

    #select the biggest liver
    #predict_liver = ndimage.binary_dilation(predict_liver, iterations=1).astype(predict_liver.dtype)
    [liver_labels, num] = measure.label(predict_liver, return_num=True)
    region = measure.regionprops(liver_labels)
    box = []
    for i in range(num):
        box.append(region[i].area)
    label_num = box.index(max(box)) + 1
    liver_labels[liver_labels != label_num] = 0
    liver_labels[liver_labels == label_num] = 1
    #predict_liver = ndimage.binary_fill_holes(liver_labels).astype(int)

    #select tumor inside the liver
    label_copy = np.zeros(liver_labels.shape)
    label_copy[liver_labels >= 1] = 1
    predict_tumor = predict_tumor * label_copy


    #select tumor biggest
    real_tumor = np.zeros(predict_tumor.shape)

    #select tumor by prob each pixel
    '''
    prob = prob * label_copy
    real_tumor[prob>=0.6] = 1
    '''


    #predict_tumor = ndimage.binary_fill_holes(predict_tumor).astype(int)
    #select tumor by max prob

    [tumor_labels, num] = measure.label(predict_tumor, return_num=True)
    region = measure.regionprops(tumor_labels)
    box = []
    for i in range(num):
        tool_array = np.zeros(tumor_labels.shape)
        tool_array[tumor_labels == i+1] = 1
        tool_array = tool_array * prob
        box.append(np.max(tool_array))
        if np.max(np.array(tool_array)) >= 0.8:
            real_tumor[tumor_labels == i+1] =1
    print(sorted(box))

    real_tumor[prob <= 0.6] = 0
    real_tumor = ndimage.binary_fill_holes(real_tumor).astype(int)


    '''
    label_copy = np.zeros(label.shape)
    label_copy[label == 2] = 1
    [_, num2] = measure.label(label_copy, return_num=True)
    print(num, num2, np.max(prob), np.min(prob))
    '''

    predict_liver[real_tumor == 1] = 2
    return predict_liver


def read_data(case_id):
    file_path = "E:\predict\image_tumor_v3"
    case_id = "case_{}".format(str(case_id).zfill(5))
    case_path = os.path.join(file_path, case_id)
    print("*"*20, case_id, "*"*20)

    liver_path = os.path.join(case_path, "label_liver")
    tumor_path = os.path.join(case_path, "label_tumor")
    output_path = os.path.join(case_path, "predict_numpy")
    prob_path = os.path.join(case_path, "prob_numpy")

    label = []
    output = []
    prob = []

    for item in sorted(os.listdir(liver_path)):
        liver_file_name = os.path.join(liver_path, item)
        liver = Image.open(liver_file_name).convert("L")
        liver = np.array(liver)
        liver = liver/255

        tumor_file_name = os.path.join(tumor_path, item)
        if os.path.isfile(tumor_file_name):
            tumor = Image.open(tumor_file_name).convert("L")
            tumor = np.array(tumor)
            liver[tumor>0] = 2
        label.append(liver)
    label = np.array(label)

    for item in sorted(os.listdir(output_path)):
        output_file = os.path.join(output_path, item)
        output_item = np.load(output_file)
        output.append(output_item)
    output = np.array(output)

    for item in sorted(os.listdir(prob_path)):
        prob_file = os.path.join(prob_path, item)
        prob_item = np.load(prob_file)
        prob.append(prob_item)
    prob = np.array(prob)

    #print(output.shape, np.unique(output))
    #print(label.shape, np.unique(label))

    tumor1 = np.zeros(output.shape)
    tumor2 = np.zeros(output.shape)
    tumor1[output == 2] = 1
    tumor2[label == 2] = 1
    dice = (2 * tumor1 * tumor2).sum() / (tumor1.sum() + tumor2.sum())
    recall = (tumor1[tumor2 == 1] == 1).sum() / (tumor2 == 1).sum()
    precision = (tumor1[tumor2 == 1] == 1).sum() / (tumor1 == 1).sum()
    print(dice, recall, precision)

    output = select_tumor(output=output, label=label, prob=prob)

    tumor1 = np.zeros(output.shape)
    tumor2 = np.zeros(output.shape)
    tumor1[output == 2] = 1
    tumor2[label == 2] = 1
    dice = (2 * tumor1 * tumor2).sum() / (tumor1.sum() + tumor2.sum())
    recall = (tumor1[tumor2 == 1] == 1).sum() / (tumor2 == 1).sum()
    precision = (tumor1[tumor2 == 1] == 1).sum() / (tumor1 == 1).sum()
    print(dice, recall, precision)

    return dice










if __name__ == '__main__':
    dice_list = []
    for case_id in [74,69,63,75,67,66,64,76,78,77,65,71,73,79,72,62]:
            dice = read_data(case_id = case_id)
            dice_list.append(dice)
    dice_list = np.array(dice_list)
    print(np.mean(dice_list))